package com.kamistoat.meimeistore.modulessystem.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kamistoat.meimeistore.apisystem.domain.SysConfig;
import com.kamistoat.meimeistore.commoncore.constant.CacheConstants;
import com.kamistoat.meimeistore.commoncore.constant.UserConstants;
import com.kamistoat.meimeistore.commoncore.exception.ServiceException;
import com.kamistoat.meimeistore.commoncore.text.Convert;
import com.kamistoat.meimeistore.commoncore.utils.StringUtils;
import com.kamistoat.meimeistore.commoncore.utils.page.Query;
import com.kamistoat.meimeistore.commonredis.utils.RedissonUtils;
import com.kamistoat.meimeistore.modulessystem.dao.SysConfigDao;
import com.kamistoat.meimeistore.modulessystem.service.SysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.kamistoat.meimeistore.commoncore.utils.page.PageUtils;
import com.kamistoat.meimeistore.apisystem.entity.SysConfigEntity;

import javax.annotation.PostConstruct;


@Service("sysConfigService")
public class SysConfigServiceImpl extends ServiceImpl<SysConfigDao, SysConfigEntity> implements SysConfigService {

    @Autowired
    RedissonUtils redissonUtils;

    /**
     * 项目启动时初始化参数缓存。
     */
    @PostConstruct
    public void init(){
        loadingConfigCache();
    }

    /**
     * 设置cache key
     *
     * @param configKey 参数键
     * @return 缓存键key
     */
    private String getCacheKey(String configKey) {
        return CacheConstants.SYS_CONFIG_KEY + configKey;
    }

    /**
     * 成功缓存
     */
    private void cacheIfSuccess(boolean success, SysConfigEntity sysConfigEntity) {
        if (success) {
            redissonUtils.setCacheObject(getCacheKey(sysConfigEntity.getConfigKey()),
                    sysConfigEntity.getConfigValue(),
                    1,
                    TimeUnit.DAYS);
        }
    }

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SysConfigEntity> page = this.page(
                new Query<SysConfigEntity>().getPage(params),
                new QueryWrapper<SysConfigEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public List<SysConfigEntity> selectConfigList(SysConfig sysConfig) {
        QueryWrapper<SysConfigEntity> sysConfigEntityQueryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(sysConfig.getConfigName())) {
            sysConfigEntityQueryWrapper.like("config_name", "%" + sysConfig.getConfigName() + "%");
        }
        if (StringUtils.isNotEmpty(sysConfig.getConfigType())) {
            sysConfigEntityQueryWrapper.eq("config_type", sysConfig.getConfigType());
        }
        if (StringUtils.isNotEmpty(sysConfig.getConfigKey())) {
            sysConfigEntityQueryWrapper.like("config_key", "%" + sysConfig.getConfigKey() + "%");
        }
        if (StringUtils.isNotEmpty((String) sysConfig.getParams().get("beginTime"))) {
            sysConfigEntityQueryWrapper.ge("create_time", sysConfig.getParams().get("beginTime"));
        }
        if (StringUtils.isNotEmpty((String) sysConfig.getParams().get("endTime"))) {
            sysConfigEntityQueryWrapper.le("create_time", sysConfig.getParams().get("endTime"));
        }
        List<SysConfigEntity> sysConfigEntityList = this.list(sysConfigEntityQueryWrapper);
        return sysConfigEntityList;
    }

    /**
     * 查 k-v并缓存
     *
     * @param configKey
     * @return
     */
    @Override
    public String selectConfigByKey(String configKey) {
        String configValue = Convert.toStr(redissonUtils.getCacheObject(getCacheKey(configKey)));
        if (StringUtils.isNotEmpty(configValue)) {
            return configValue;
        }

        SysConfigEntity one = this.getOne(new QueryWrapper<SysConfigEntity>().select("config_value").eq("config_key", configKey));

        if (StringUtils.isNotNull(one) && StringUtils.isNotEmpty(one.getConfigValue())) {
            cacheIfSuccess(true, one);
            return one.getConfigValue();
        }

        return StringUtils.EMPTY;
    }

    /**
     * 检查 SysConfig是否已经存在
     * 其实就是检查 config_key 是否已经存在
     */
    @Override
    public boolean checkConfigKeyUnique(SysConfig sysConfig) {
        SysConfigEntity one = this.getOne(new QueryWrapper<SysConfigEntity>().select("config_id").eq("config_key", sysConfig.getConfigKey()));
        // 同时考虑新增 / 修改 的两种重复情况
        return StringUtils.isNotNull(one) && StringUtils.isNotNull(one.getConfigId()) && !one.getConfigId().equals(sysConfig.getConfigId());
    }

    @Override
    public boolean saveAndCache(SysConfigEntity sysConfigEntity) {
        boolean save = this.save(sysConfigEntity);
        cacheIfSuccess(save, sysConfigEntity);
        return save;
    }

    @Override
    public boolean updateByIdAndCache(SysConfigEntity sysConfigEntity) {
        boolean updateById = this.updateById(sysConfigEntity);
        cacheIfSuccess(updateById, sysConfigEntity);
        return updateById;
    }

    @Override
    public boolean deleteConfigByIdsAndRemoveCache(Long[] configIds) {
        List<SysConfigEntity> deleteList = this.list(
                new QueryWrapper<SysConfigEntity>().
                        select("config_id", "config_key", "config_type").
                        in("config_id", configIds));

        for (SysConfigEntity deleteEntity : deleteList) {
            if (deleteEntity.getConfigType().equals(UserConstants.YES)) {
                throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", deleteEntity.getConfigKey()));
            }
            boolean removeById = this.removeById(deleteEntity.getConfigId());
            redissonUtils.deleteObject(getCacheKey(deleteEntity.getConfigKey()));
            if (!removeById) {
                throw new ServiceException(String.format("参数【%1$s】删除失败 ", deleteEntity.getConfigKey()));
            }
        }
        return true;
    }

    /**
     * 重新加载参数缓存
     */
    @Override
    public void resetConfigCache() {
        clearConfigCache();
        loadingConfigCache();
    }

    /**
     * 清空参数缓存数据
     */
    public void clearConfigCache() {
        Collection<String> keys = redissonUtils.keys(CacheConstants.SYS_CONFIG_KEY + "*");
        redissonUtils.deleteObject(keys);
    }

    /**
     * 加载参数缓存数据
     */
    public void loadingConfigCache() {
        List<SysConfigEntity> sysConfigEntityList = this.list();
        for (SysConfigEntity sysConfigEntity : sysConfigEntityList) {
            redissonUtils.setCacheObject(getCacheKey(sysConfigEntity.getConfigKey()),
                    sysConfigEntity.getConfigValue(),
                    CacheConstants.EXPIRATION,
                    TimeUnit.MINUTES);
        }
    }
}